package Utils.basicDataTypes;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Spliterator;
import java.util.function.Consumer;

/**
 * 树状结构
 *
 * @author d11yu
 */
public class TreeNode<T> implements Iterable<TreeNode<T>> {
    public T data;
    public TreeNode<T> parent;
    public List<TreeNode<T>> children;
    public int level;

    /**
     * 构造函数
     *
     * @param data 当前节点数据
     */
    public TreeNode(T data) {
        this.data = data;
        this.level = 0;
        this.children = new LinkedList<TreeNode<T>>();
    }

    /**
     * 构造函数
     *
     * @param data  当前节点数据
     * @param level 当前节点级别
     */
    private TreeNode(T data, int level) {
        this.data = data;
        this.level = level;
        this.children = new LinkedList<TreeNode<T>>();
    }

    /**
     * 添加子节点
     *
     * @param child 要添加的数据
     */
    public TreeNode<T> add(T child) {
        TreeNode<T> childNode = new TreeNode<T>(child, level + 1);
        childNode.parent = this;
        this.children.add(childNode);
        return childNode;
    }

    /**
     * 当前节点是否有子节点
     */
    public boolean hasChildNode() {
        return (this.children != null && this.children.size() > 0);
    }

    //region Implemented Methods
    @Override
    public Iterator<TreeNode<T>> iterator() {
        return new Itr(0);
    }

    @Override
    public void forEach(Consumer<? super TreeNode<T>> action) {
        Iterable.super.forEach(action);
    }

    @Override
    public Spliterator<TreeNode<T>> spliterator() {
        return Iterable.super.spliterator();
    }
    //endregion

    /**
     * 自定义迭代器
     */
    class Itr implements Iterator<TreeNode<T>> {
        int index;
        int lastRet = -1;

        @Override
        public boolean hasNext() {
            return index < children.size();
        }

        @Override
        public TreeNode<T> next() {
            lastRet = index;
            index++;
            return children.get(lastRet);
        }

        public Itr(int index) {
            this.index = index;
        }
    }
}
